#web页面显示温湿度线状图
#后台使用fastapi做网页框架，tinydb做数据库，显示通过pyecharts显示线状图，并设计了包含各类配置的web管理
#另一个程序每分钟从温湿度计上，蓝牙读取小米温湿度计2的温湿度和电池数据，并tinydb数据库写入当天的json文件中。
from fastapi import FastAPI
from starlette.responses import HTMLResponse
import uvicorn
from pyecharts import options as opts
from pyecharts.charts import Line
import os,sys,time,datetime
from pyecharts.components import Table
from pyecharts.options import ComponentTitleOpts
from starlette.staticfiles import StaticFiles
from pyecharts.globals import CurrentConfig
from tinydb import TinyDB, Query
from typing import Optional
from starlette.responses import RedirectResponse

#设定文件夹，切换当前路径， 保证python脚本从哪个目录都可以正常运行
current_path=os.path.dirname(os.path.abspath(sys.argv[0]))
print('hello1',current_path)
if current_path=='':
    current_path='./'
os.chdir(current_path)

#网页的head头部， 设定刷新频率等
head='''
<html>
<head>
<meta http-equiv="refresh" content="300">
</head>
<body>
'''

#各类设定的web页面
settings_page='''
<form action="/done">
<br>小米温湿度计蓝牙MAC地址:
<input type="text" name="MAC" value={}></br>
<br>高温报警：摄氏度
<input type="text" name="tmp_max" value={}></br>
<br>湿度报警:百分比
<input type="text" name="hmt_max" value={}></br>
<br>低电量报警:百分比
<input type="text" name="baterry" value={}></br>
<br>网页标题名称:
<input type="text" name="title" value={}></br>
<br>时间服务器:
<input type="text" name="NTP" value={}></br>
<br>告警邮件发送人:
<input type="text" name="sender" value={}></br>
<br>告警邮件接收人:
<input type="text" name="receivers" value={}></br>
<br>邮件服务器:
<input type="text" name="mail_server" value={}></br>
<br>告警邮件标题:
<input type="text" name="email_title" value={}></br>
<br>告警邮件内容:
<input type="text" name="email_content" value={}></br>
<br>
<input type="submit" value="Submit"></br>
</form> 
'''

#固定ip
staticip_page='''
<form method="get" action="static_ip">
IP：<input type="text" name="ip"/>  gateway：<input type="text" name="gateway"/> DNS：<input type="text" name="dns"/>  <input type="submit" value="Submit"/>
</form>
'''
#管理菜单
admin_menu='''
<br><a href="./DHCP">0.网线接口 动态IP DHCP</a></br>
<br><a href="./static_ip">1.网线接口固定IP</a></br>
<br><a href="./settings">2.其它告警设定</a></br>
<br><a href="./reboot">3.重启</a></br>
'''
#密码表单
password_form='''
<form name="input" action="?" method="get">
Password: <input type="password" name="pwd">
<input type="submit" value="Submit">
</form>
'''

#日期表单
date_form='''
<form>
  <div align="center">当前温度:<b>{}</b> ℃ 湿度:<b>{}</b> % 剩余电量:<b>{}</b> %
    <label for="bday">历史记录:</label>
    <input type="date" id="bday" name="bday">
<input type="submit"><a href="/admin">管理</a></div> 
</form>
'''

#温湿度线图，调用pyecharts,参考自https://gallery.pyecharts.org/#/Line/temperature_change_line_chart
def line(file,title0='主标题',title1='副标题'):
    config = TinyDB('config.json')
    title=config.all()[0]['title']
    config.close()
    db = TinyDB(file)
    all_data=db.all()
    db.close()
    print('here',all_data)


    #print(list(map(lambda x:x['time'],db.all())))
    week_name_list = list(map(lambda x:x['time'],all_data))
    high_temperature = list(map(lambda x:x['tmp'],all_data))
    low_temperature = list(map(lambda x:x['hmt'],all_data))
    c=Line(init_opts=opts.InitOpts(width="1200px", height="400px",js_host= "/static/"))
    c.add_xaxis(xaxis_data=week_name_list)
    c.add_yaxis(
        series_name="温度",
        y_axis=high_temperature,
        markpoint_opts=opts.MarkPointOpts(
            data=[
                opts.MarkPointItem(type_="max", name="最大值"),
                opts.MarkPointItem(type_="min", name="最小值"),
            ]
        ),
        markline_opts=opts.MarkLineOpts(
            data=[opts.MarkLineItem(type_="average", name="平均值")]
        ),
    )
    c.add_yaxis(
        series_name="湿度",
        y_axis=low_temperature,
        markpoint_opts=opts.MarkPointOpts(
            data=[
                opts.MarkPointItem(type_="max", name="最大值"),
                opts.MarkPointItem(type_="min", name="最小值"),]
#opts.MarkPointItem(value=-2, name="周最低", x=1, y=-1.5)]
        ),
        markline_opts=opts.MarkLineOpts(
            data=[
#                opts.MarkPointItem(type_="max", name="最大值"),
#                opts.MarkPointItem(type_="min", name="最小值"),                
                opts.MarkLineItem(type_="average", name="平均值"),
#                opts.MarkLineItem(symbol="none", x="90%", y="max"),
#                opts.MarkLineItem(symbol="circle", type_="max", name="最高点"),
            ]
        ),
    )
    c.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
    c.set_global_opts(
        title_opts=opts.TitleOpts(title=title),
        tooltip_opts=opts.TooltipOpts(trigger="axis"),
        toolbox_opts=opts.ToolboxOpts(is_show=True),
        xaxis_opts=opts.AxisOpts(type_="category", boundary_gap=False),
    )
    try:
        return date_form.format(all_data[-1]['tmp'],all_data[-1]['hmt'],all_data[-1]['battery'])+c.render_embed()
    except:
        return date_form.format(0,0,0)+c.render_embed()



app = FastAPI()

#加载static目录，包含一些js文件
app.mount('/static', StaticFiles(directory='./static'), name='static')

#home目录 默认去当天的数据
@app.get("/")
def home(bday: Optional[str] = None):
    if bday:
        date=bday
    else:
        date = datetime.datetime.now().strftime("%Y-%m-%d")
    return HTMLResponse(content=head+line('history/'+date+'.json'))

#管理界面
@app.get("/admin")
def admin(pwd: Optional[str] = None):
    if pwd=='rootpasswd':
        return HTMLResponse(content=admin_menu)
    else:

        return HTMLResponse(content=password_form)
#DHCP菜单
@app.get('/DHCP')
def DHCP():
    os.system('cp -f ./static/dhcp.conf /etc/dhcpcd.conf')
    time.sleep(1)
    os.system('reboot')
    return  HTMLResponse(content='重启生效中')


#固定IP
@app.get('/static_ip')
def static_ip(ip: Optional[str] = None,gateway: Optional[str] = None,dns: Optional[str] = None):
    if ip and gateway:
        with open('./static/dhcpcd.conf','r') as f:
            x=f.readlines()
        line1='interface eth0'
        line2='static ip_address='+ip+'/24'
        line3='static routers='+gateway
        line4='static domain_name_servers='+dns
        x.append(line1+'\n')
        x.append(line2+'\n')
        x.append(line3+'\n')
        x.append(line4+'\n')
        for x0 in x:
            print(x0)

        with open('/etc/dhcpcd.conf','w') as f:
            for x0 in x:
                f.write(x0)
        time.sleep(1)
        os.system('reboot')
        return  HTMLResponse(content='重启生效中')
    else:
        return  HTMLResponse(content=staticip_page)
#w高温报警设定页面
@app.get('/settings')
def tmp_max():
    db = TinyDB('config.json')
#    db.insert({'id':1,'tmp_max': 32, 'hmt_max': 90,'baterry':10,'title':'这是标题','NTP':'10.102.10.1',\
#'sender':'jianbo.wang@gi-de.com','receivers':'jianbo.wang@gi-de.com','mail_server':'10.4.172.3',\
#'email_title':'this is email title','email_content':'this is email content'})
    User=Query()
    #db.update({'tmp_max': tmp_max}, User.id == 1)
    result=db.all()
    db.close()
    default=list(result[0].values())[1:]
    print(default)
    return  HTMLResponse(content=settings_page.format(default[0],default[1],default[2],default[3],default[4],default[5],default[6],default[7],default[8],default[9],default[10]))
#w高温报警设定返回
@app.get('/done')
def done(MAC: Optional[str] = None,tmp_max: Optional[str] = None,hmt_max: Optional[str] = None,baterry: Optional[str] = None,title: Optional[str] = None,\
NTP: Optional[str] = None,sender: Optional[str] = None,receivers:Optional[str] = None,mail_server: Optional[str] = None,email_title: Optional[str] = None,email_content: Optional[str] = None,):
    db = TinyDB('config.json')
#    db.insert({'id':1,'tmp_max': 32, 'hmt_max': 90,'baterry':10,'title':'这是标题','NTP':'10.102.10.1',\
#'sender':'jianbo.wang@gi-de.com','receivers':'jianbo.wang@gi-de.com','mail_server':'10.4.172.3',\
#'email_title':'this is email title','email_content':'this is email content'})
    User=Query()
    db.update({'MAC':MAC,'tmp_max': tmp_max,'hmt_max': hmt_max,'baterry':baterry,'title':title,'NTP':NTP,'mail_server':mail_server,\
'sender':sender,'receivers':receivers,'email_title':email_title,'email_content':email_content}, User.id == 1)
    result=db.all()
    db.close()
    default=list(result[0].values())[1:]
    print(default)
    return RedirectResponse(url='/')
    #return  HTMLResponse(content='请手动返回')
#重启
@app.get('/reboot')
def reboot():
    os.system('sudo reboot')
    return  HTMLResponse(content='重启生效中')
#主函数定义端口
if __name__ == "__main__":
    #print('当前程序名称为:',os.path.basename(__file__))
    #filename=os.path.basename(__file__).split('.')[0]
    filename=os.path.basename(sys.argv[0]).split('.')[0]
    #print(filename,os.getcwd(),os.path.dirname(os.path.realpath('__file__')))
    #os.chdir(current_path)
    uvicorn.run('{}:app'.format(filename), host="0.0.0.0",port=80,log_level="info",workers=5,reload=True)
